﻿using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Reflection.Emit;
using System.Runtime.Caching;
using System.Text;
using UFIDA.U9.Base;
using UFIDA.U9.Base.Profile;
using UFIDA.U9.CBO.SCM.Customer;
using UFIDA.U9.CBO.SCM.Item;
using UFIDA.U9.Cust.LS.PlugBE.utils;
using UFIDA.U9.MO.Enums;
using UFIDA.U9.MO.WF;
using UFIDA.U9.PM.PC;
using UFIDA.U9.PM.PO;
using UFIDA.U9.PM.Rcv;
using UFIDA.U9.PR.PurchaseRequest;
using UFIDA.U9.SM.RMA;
using UFIDA.U9.SM.Ship;
using UFIDA.U9.SM.SO;
using UFSoft.UBF.Business;
using UFSoft.UBF.Eventing;
using UFSoft.UBF.PL;
using UFSoft.UBF.PL.Engine;
using UFSoft.UBF.PL.ObjectAccess;
using UFSoft.UBF.Util.DataAccess;


namespace UFIDA.U9.Cust.LS.PlugBE
{
    /// <summary>
    /// 爱发科
    /// 请购单
    /// 
    /// 提交时,清空同步标志
    /// 
    /// 1.1请购单现存量查询:
    /// 1.需求人员在U9C系统录入请购单，系统根据料号+指定指番+指定仓库（参数设置，待确认）
    /// 显示可供应数量（指定仓库+指番+公共指番可用量+对应料品+对应指番+公共指番的在途），
    /// 点击保存按钮触发计算逻辑。
    /// </summary>
    class AFKPRExtend : IEventSubscriber
    {
        //配置XX.sub.xml文件放置到portal/bin下，dll文件放置到portal/ApplicationServer/Libs下
        public void Notify(params object[] args)
        {
            if (args != null && args.Length != 0 && args[0] is EntityEvent)
            {
                BusinessEntity.EntityKey key = ((EntityEvent)args[0]).EntityKey;
                UFIDA.U9.PR.PurchaseRequest.PR be = key.GetEntity() as UFIDA.U9.PR.PurchaseRequest.PR;
                if (be == null)
                    return;

                if (be.SysState == ObjectState.Inserted)
                {
                    //新增/复制
                    //初始版本
                    be.DescFlexField.PrivateDescSeg6 = "";
                }
                if (be.Status == PRStatusEnum.OpenOpen)
                {
                    if (be.DocType.Code == "cs") return;
                    //保存
                    //可用量更新
                    KYLUpdate(be);
                }
                else if ((be.Status == PRStatusEnum.Approving && be.OriginalData.Status == PRStatusEnum.OpenOpen))
                {
                    // 提交时
                    // 清空同步标志
                    UpdateSyncFlag(be);
                    //版本+1
                    AddVersion(be);
                }
                if (be.Status == PRStatusEnum.Approved && be.OriginalData.Status == PRStatusEnum.Approving)
                {
                    ApproveProcess(be);
                }
            }
        }
        /// <summary>
        /// 请购审核时,如果生产订单已经完工,则把单据改为开立状态
        /// </summary>
        /// <param name="be"></param>
        /// <exception cref="Exception"></exception>
        private void ApproveProcess(PR.PurchaseRequest.PR be)
        {
            //请购审核时,单据类型是PR1或者PR3的时候(专用件请购,工序委外请购)
            if (be.DocType.Code == "PR1" || be.DocType.Code == "PR3")
            {
                //如果生产订单已经完工,则把单据改为开立状态
                foreach (var line in be.PRLineList)
                {
                    if (!string.IsNullOrEmpty(line.DescFlexSegments.PrivateDescSeg2))
                    {
                        UFIDA.U9.MO.MO.MO mo = UFIDA.U9.MO.MO.MO.Finder.Find("DocNo='" + line.DescFlexSegments.PrivateDescSeg2 + "'");
                        if (mo != null)
                        {
                            if (mo.DocState == MOStateEnum.Complete)
                            {
                                MOUnApprove(be);
                            }
                        }
                        else
                        {

                            throw new Exception("生产订单查询异常");
                        }
                    }
                }
            }
        }

        /// <summary>
        /// 请购审核时,如果生产订单已经完工,则把单据改为开立状态
        /// </summary>
        /// <param name="be"></param>
        /// <exception cref="NotImplementedException"></exception>
        private void MOUnApprove(PR.PurchaseRequest.PR Doc)
        {
           foreach(var line in Doc.PRLineList)
            {

                UFIDA.U9.MO.MO.MO mO = UFIDA.U9.MO.MO.MO.Finder.Find("DocNo='" + line.DescFlexSegments.PrivateDescSeg2 +"'");
                if (mO != null)
                {
                     
                    DateTime dateTime = DateTime.Now;
                    if (dateTime > mO.ActualCompleteDate.ToUniversalTime()&& 
                        dateTime.Year!=mO.ActualCompleteDate.Year||dateTime.Month!=mO.ActualCompleteDate.Month)
                    {
                        Doc.Status = PRStatusEnum.OpenOpen;
                        throw new Exception($"请购单[{Doc.DocNo}]审核日期大于[{mO.DocNo}]生产订单完工日期,并且已跨月");
                    }
                }
                

            }

         }

        /// <summary>
        /// 请购单库存查询
        /// 更新 需求数量(标准)
        /// </summary>
        /// <param name="be"></param>
        /// <exception cref="NotImplementedException"></exception>
        private void KYLUpdate(PR.PurchaseRequest.PR doc)
        {
            //可用量缓存
            Dictionary<String, decimal> map = new Dictionary<string, decimal>();

            foreach (var line in doc.PRLineList)
            {
                long itemid = line.ItemInfo.ItemID.ID;//料品

                string projcodes = GetParam("AFKPRQOHPROJ",Context.LoginOrg.Code);//公共项目 通过参数获取
                string whcodes = GetParam("AFKPRQOHCK", Context.LoginOrg.Code);//仓库 通过参数获取

                if (string.IsNullOrEmpty(line.DescFlexSegments.PrivateDescSeg9)) 
                    throw new Exception("需求数量(手工)为空");
                decimal sgsl = decimal.Parse(line.DescFlexSegments.PrivateDescSeg9);//需求数量(手工)


                if (string.IsNullOrEmpty(projcodes) && string.IsNullOrEmpty(whcodes))
                {
                    // 没填参数设置 把手工数量赋值给标准字段
                    line.ReqQtyReqUOM = sgsl;//需求数量1
                    line.ApprovedQtyReqUOM = sgsl;//核准数量1
                    line.ReqQtyTU = sgsl;// 需求数量1采购单位
                    line.ReqQtyPU = sgsl;// 需求数量1 
                    line.ApprovedQtyTU = sgsl;// 需求数量1采购单位
                    line.ApprovedQtyPU = sgsl;// 需求数量1
                }
                else
                {
                    //参数设置一个,就进行可用量计算
                    String whPath;
                    String projPath;
                    //项目条件拼接
                    if (projcodes.Length > 1 && projcodes[0] == '"' && projcodes[projcodes.Length - 1] == '"')
                    {
                        projcodes = projcodes.Trim('"');
                    }
                    string[] projcodelist = projcodes.Split(',');
                    string projcodepath = string.Join("','", projcodelist);
                    if (projcodepath.Length > 0 && !string.Join("", projcodepath).Equals(""))
                    {
                        projPath = $"and proj.Code in ('{projcodepath}')";
                    }
                    else
                    {
                        projPath = "";
                    }

                    //仓库条件拼接
                    if (whcodes.Length > 1 && whcodes[0] == '"' && whcodes[whcodes.Length - 1] == '"')
                    {
                        whcodes = whcodes.Trim('"');
                    }
                    string[] whcodelist = whcodes.Split(',');
                    string whcodepath = string.Join("','", whcodelist);
                    if (whcodelist.Length > 0 && !string.Join("", whcodelist).Equals(""))
                    {
                        whPath = $"and wh.Code in ('{whcodepath}')";
                    }
                    else
                    {
                        whPath = "";
                    }

                    decimal kyl = 0; //可用量
                    Dictionary<string, object> kylDic = new Dictionary<string, object>();//可用量计算集合
                    //查询缓存
                    string key = Context.LoginOrg.ID + "-" + whPath + "-" + projPath + "-" + itemid;
                    if (map.ContainsKey(key))
                    {
                        //缓存中获取
                        kyl = map[key];
                    }
                    else
                    {
                        //数据库获取
                        List<Dictionary<string, object>> retlist = AFKUtils.GetKyl(itemid, whPath, projPath, line.Project.ID);
                        kylDic = retlist[0];
                        kyl = (decimal)kylDic["kyl"];
                    }
                    // 更新需求数量
                    decimal sykyl = kyl - sgsl; //剩余可用量
                    // 剩余可用量赋值
                    line.DescFlexSegments.PrivateDescSeg10 = sykyl.ToString();

                    //计算起订量/倍量
                    ItemMaster item = ItemMaster.Finder.Find("id='" + line.ItemInfo.ItemID.ID + "'");
                    decimal minqty = item.PurchaseInfo.MinRcvQty; //最小起订量
                    decimal batchqt = item.PurchaseInfo.PurchaseBatchQty; //倍量
                    decimal poQty = 0;//采购数量
                    if (sykyl < 0)
                    {
                        //需求>供给 不消库
                        line.DescFlexSegments.PrivateDescSeg8 = "False"; //是否消库
                        poQty = sykyl*-1;
                        //// 优先处理倍量
                        if (batchqt > 0)
                        {
                            // 计算倍量的整数倍
                            poQty = Math.Ceiling(poQty / batchqt) * batchqt;
                        }
                        // 如果没有倍量但有最小起订量，且数量不足最小起订量
                        else if (minqty > 0 && poQty < minqty)
                        {
                            poQty = minqty;
                        }
                        
                    }
                    else
                    {
                        // 要消库
                        line.DescFlexSegments.PrivateDescSeg8 = "true"; //是否消库
                        poQty = sgsl;
                    }
                    // 设置各数量字段
                    line.ReqQtyReqUOM = poQty;
                    line.ApprovedQtyReqUOM = poQty;
                    line.ReqQtyTU = poQty;
                    line.ReqQtyPU = poQty;
                    line.ApprovedQtyTU = poQty;
                    line.ApprovedQtyPU = poQty;
                    kyl -= sgsl; //剩余可用量=可用量-需求数量
                    line.DescFlexSegments.PrivateDescSeg20 = kylDic["kc_sl"].ToString();//库存数量
                    line.DescFlexSegments.PrivateDescSeg21 = kylDic["qgzt_sl"].ToString();//请购在途数量
                    line.DescFlexSegments.PrivateDescSeg22 = kylDic["cgzt_sl"].ToString();//采购在途数量
                    line.DescFlexSegments.PrivateDescSeg23 = kylDic["qgxq_sl"].ToString();//请购需求数量
                    line.DescFlexSegments.PrivateDescSeg24 = kylDic["scwl_sl"].ToString();//生产未领数量
                    line.DescFlexSegments.PrivateDescSeg25 = kylDic["xswf_sl"].ToString();//销售未出数量
                    line.DescFlexSegments.PrivateDescSeg26 = kylDic["zfwl_sl"].ToString();//杂发未出数量

                    //更新缓存可用量
                    if (map.ContainsKey(key))
                    {
                        map[key] = kyl;
                    }
                    else
                    {
                        map.Add(key, kyl);
                    }
                }

                
            }
        }

        

        /// <summary>
        /// 读取U9参数
        /// </summary>
        /// <param name="code"></param>
        /// <param name="orgcode"></param>
        /// <returns></returns>
        private static string GetParam(string code,string orgcode)
        {
            Profile profile = Profile.Finder.Find($"Code='{code}'");
            if (profile == null || profile.ProfileValues == null || profile.ProfileValues.Count == 0)
                return "";
            if (string.IsNullOrEmpty(orgcode))
            {
                return profile.ProfileValues[0].Value;
            }
            else
            {
                foreach (ProfileValue value in profile.ProfileValues)
                {
                    if (value.Organization.Code == orgcode)
                    {
                        return value.Value;
                    }
                }
            }
            throw new Exception($"获取参数[{code}]失败!");
        }

        /// <summary>
        /// 版本+1
        /// </summary>
        /// <param name="be"></param>
        private static void AddVersion(PR.PurchaseRequest.PR be)
        {
            if (string.IsNullOrEmpty(be.DescFlexField.PrivateDescSeg6))
            {
                //版本初始2
                be.DescFlexField.PrivateDescSeg6 = "1";
            }
            else
            {
                //版本+1
                int ver = Int32.Parse(be.DescFlexField.PrivateDescSeg6);
                be.DescFlexField.PrivateDescSeg6 = (ver + 1).ToString();
            }
        }
        /// <summary>
        /// 清除同步标志
        /// </summary>
        /// <param name="be"></param>
        private static void UpdateSyncFlag(PR.PurchaseRequest.PR be)
        {
            DateTime now = DateTime.Now;
            string formatted = now.ToString("yyyy-MM-dd HH:mm:ss");
            //String sql = $"Update pr_pr set DescFlexField_PrivateDescSeg3='',DescFlexField_PrivateDescSeg4='{formatted}' WHERE docno='{be.DocNo}'";
            //DataAccessor.RunSQL(DataAccessor.GetConn(), sql, null);
            be.DescFlexField.PrivateDescSeg3 = "";
            be.DescFlexField.PrivateDescSeg4 = formatted;
        }
    }
}
